﻿using UnityEngine;
using System.Collections;

namespace KaoticSSB
{
	public class SoundManager : MonoBehaviour 
	{
		private static bool mSwapping = false;
		private static bool mFadingIn = true;
		private static bool mFadingOut = false;
		private static float mTimeRemainingUntilFade = 0.0f;
		private static float mTimeUntilFade = 0.0f;
		private static AudioClip mNextAudioClip = null;
		private static float mNextAudioClipFadeInTime = 0.0f;

		public static SoundManager GetInstance()
		{
			return mInstance;
		}

		void Awake()
		{
			if( mInstance != null && mInstance != this )
			{
				Destroy ( this.gameObject );
				return;
			}
			else
			{
				mInstance = this;
			}
			DontDestroyOnLoad(this.gameObject);
		}

		// Use this for initialization
		void Start () 
		{
		
		}
		
		/*
		 * \brief called once per frame
		 * Fades in or out depending on state
		 */
		void Update () 
		{
			if(mFadingOut)	
			{
				FadeOut();
			}
			if(mFadingIn)
			{
				FadeIn();
			}
			if(mSwapping)
			{
				SwapTracks ();
			}
		}

		/**
		 * \brief Instantly play specified music clip
		 */
		public void PlayMusic(AudioClip clip)
		{
			if(!audio.isPlaying)
			{
				audio.clip = clip;
				audio.loop = true;
				audio.Play();
			}
		}

		/**
		 * \brief Music fades in over a specified number of seconds
		 */
		public void PlayMusicOverTime(AudioClip clip, float seconds)
		{
			if(!audio.isPlaying)
			{
				audio.clip = clip;
				audio.loop = true;
				mTimeUntilFade = seconds;
				mTimeRemainingUntilFade = seconds;
				mFadingIn = true;
				audio.volume = 0.0f;
				audio.Play ();
			}
  		}

		/*
		 * \brief Music fades in over a specified number of seconds
		 */
		public void PlayMusicOverTime(string clipName, float seconds)
		{
			AudioClip clip = Resources.Load<AudioClip> ("Audio/Music/" + clipName);
			if(clip != null)
			{
				PlayMusicOverTime(clip, seconds);
			}
			else
			{
				throw new UnityException("Could not find Audio clip(" + clipName + ")");
			}
		}

		/**
		 * \brief Swap out the current music track with another, but fade out the first one and in the second one
		 */
		public void SwapTracksWithFade(AudioClip clip, float durationIn, float durationOut)
		{
			if(!mSwapping)
			{
				mSwapping = true;
				mNextAudioClip = clip;
				StopMusicOverTime(durationOut);
			}
		}

		/**
		 * \brief when the first audio clip stops playing, start up the next audio clip
		 */
		private void SwapTracks()
		{
			if(!audio.isPlaying)
			{
				mSwapping = false;
				PlayMusicOverTime(mNextAudioClip, mNextAudioClipFadeInTime);
			}
		}

		/**
		 * \brief Instantly stop current music track
		 */
		public void StopMusic()
		{
			if(audio.isPlaying)
			{
				audio.Stop ();
			}
		}

		/**
		 * \brief Music fades out over a specified number of seconds
		 */
		public void StopMusicOverTime(float seconds)
		{
			if(audio.isPlaying)
			{
				mTimeUntilFade = seconds;
				mTimeRemainingUntilFade = seconds;
				mFadingOut = true;
			}
		}

		private void FadeIn()
		{
			mTimeRemainingUntilFade -= Time.deltaTime;
			if(mTimeRemainingUntilFade <= 0.0f)
			{
				mFadingIn = false;
				audio.volume = 1.0f;
			}
			else
			{
				audio.volume = ( (mTimeUntilFade - mTimeRemainingUntilFade) / mTimeUntilFade);
			}
		}

		private void FadeOut()
		{
			mTimeRemainingUntilFade -= Time.deltaTime;
			if(mTimeRemainingUntilFade <= 0.0f)
			{
				mFadingOut = false;
				audio.Stop ();
				audio.volume = 1.0f;
			}
			else
			{
				audio.volume = (mTimeRemainingUntilFade / mTimeUntilFade);
			}
		}

		private static SoundManager mInstance = null;
	}
}